package com.dmz.mybatis.interceptor;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @Intercepts    // 描述：标志该类是一个拦截器
 * @Signature注解参数说明
 * type 四个可拦截类的class对象；
 * method 类中的方法名称，入上述的prepare就是StatementHandler中的prepare方法；
 * args 方法的形参类型，数量类型与拦截类中的方法声明一致
 *
 */
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MyInterceptor implements Interceptor {

    /* ... */

    Properties properties = null;

    /**
     * 拦截方法逻辑
     * 这里主要是通过反射去获取要执行的SQL相关信息，然后进行操作
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        Object target = invocation.getTarget(); //被代理对象
        Method method = invocation.getMethod(); //代理方法
        Object[] args = invocation.getArgs(); //方法参数

        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object parameterObject = args[1];

        // do something ...方法拦截前执行代码块

        Object result = invocation.proceed();

        // do something ...方法拦截后执行代码块

        return result;

    }

    /**
     * 生成MyBatis拦截器代理对象
     */
    @Override
    public Object plugin(Object target) {
        if(target instanceof Executor){
            // 调用插件
            return Plugin.wrap(target, this);
        }
        return target;
    }

    /**
     * 设置插件属性（直接通过Spring的方式获取属性，所以这个方法一般也用不到）
     * 项目启动的时候数据就会被加载
     */
    @Override
    public void setProperties(Properties properties) {
        // 赋值成员变量，在其他方法使用
        this.properties = properties;
    }

    /* ... */

}